﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufExtension.h"
#include "GnufCommonLineStyleButton.h"
#include "ElementId.h"

namespace gcmp
{
    class IDocument;
    class ILineTypeNew;
    class IGraphicsStyle;
}

namespace gnuf {

    class DropDownBoard;
    template<typename T>
    class CommonLineSyleButtonModelWith : public CommonLineStyleButtonModel
    {
    public:
        void setSourceData(const std::vector<const T*>& src)
        {
            if (src.empty() || src == m_src) return;
            m_src = src;
            m_srcPixmapStream.clear();
            m_srcPixmapStream.resize(m_src.size());
        }

    protected:
        virtual void onPaintLineStyleItems(DropDownBoard* dropDownBoard) override
        {
            DBG_WARN_AND_RETURN_VOID_UNLESS(dropDownBoard, L"dropdownboard is nullptr", L"GMEP", L"2021-04-13");
            const AppearanceSetting * pAppearanceSetting = dropDownBoard->appearanceSetting();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pAppearanceSetting, L"pAppearanceSetting is nullptr!", L"GMEP", L"2022-06-30");
            const DropDownBoardAppearanceSetting* pDropDownSetting = pAppearanceSetting->dropDownBoardAppearanceSetting();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pDropDownSetting, L"pDropDownSetting is nullptr!", L"GMEP", L"2022-06-30");

            const ButtonAppearanceSetting* menuItemAppearanceSetting = pDropDownSetting->menuItemAppearanceSetting();
            if (menuItemAppearanceSetting == nullptr) return;

            for (int i = 0; i < m_src.size(); i++)
            {
                const T* src = m_src[i];
                DBG_WARN_AND_CONTINUE_UNLESS(src, L"src is nullptr!", L"GMEP", L"2022-06-30");
                gcmp::OwnerPtr<ButtonEx> button = ButtonEx::make(EItemType::ePushButton, dropDownBoard);

                DBG_WARN_AND_RETURN_VOID_UNLESS(m_srcPixmapStream.size() == m_src.size(), L"m_srcPixmapStream.size error", L"GMEP", L"2021-11-22");
                std::wstring pixmapStream = m_srcPixmapStream[i];
                gcmp::OwnerPtr<Info> btnInfo = onGetButtonInfo(src);
                if (pixmapStream.empty())
                {
                    onBuildLineSyleItem(src, { 40, 24 }, pixmapStream);
                    m_srcPixmapStream[i] = pixmapStream;
                }

                button->assignInfo(*btnInfo, pixmapStream);
                dropDownBoard->addMenuItem(TransferOwnership(button));
            }
        }

        virtual gcmp::OwnerPtr<Info> onGetButtonInfo(const T*) = 0;
        virtual void onBuildLineSyleItem(const T*, const std::pair<int, int>& size, std::wstring&) = 0;

    private:
        std::vector<const T*> m_src;
        std::vector<std::wstring> m_srcPixmapStream;
    };

    class GNUF_EXTENSION_EXPORT LineStyleButtonModel
        : public CommonLineSyleButtonModelWith<gcmp::IGraphicsStyle>
    {
    protected:
        virtual gcmp::OwnerPtr<Info> onGetButtonInfo(const gcmp::IGraphicsStyle*) override;
        virtual void onBuildLineSyleItem(const gcmp::IGraphicsStyle*, const std::pair<int, int>& size, std::wstring&) override;
    };

    class GNUF_EXTENSION_EXPORT LinePatternButtonModel
        : public CommonLineSyleButtonModelWith<gcmp::ILineTypeNew>
    {
    protected:
        virtual gcmp::OwnerPtr<Info> onGetButtonInfo(const gcmp::ILineTypeNew*) override;
        virtual void onBuildLineSyleItem(const gcmp::ILineTypeNew*, const std::pair<int, int>& size, std::wstring&) override;
    };

    class GNUF_EXTENSION_EXPORT LineWidthButtonModel
        : public CommonLineSyleButtonModelWith<int>
    {
    protected:
        virtual gcmp::OwnerPtr<Info> onGetButtonInfo(const int*) override;
        virtual void onBuildLineSyleItem(const int*, const std::pair<int, int>& size, std::wstring&) override;
    };

    class GNUF_EXTENSION_EXPORT CadLineWidthButtonModel
        : public CommonLineSyleButtonModelWith<std::pair<int, double>>
    {
    protected:
        virtual gcmp::OwnerPtr<Info> onGetButtonInfo(const std::pair<int, double>*) override;
        virtual void onBuildLineSyleItem(const std::pair<int, double>*, const std::pair<int, int>& size, std::wstring&) override;
    };

    class GNUF_EXTENSION_EXPORT LineStyleButtonModelFactory final
    {
        CANNOT_COPY_OR_ASSIGN(LineStyleButtonModelFactory)
    public:
        enum LineStyleButtonModelType : std::uint8_t
        {
            eLineStyle = 0,
            eLinePattern,
            eLineWidth,
            eCadLineWidth
        };
        static LineStyleButtonModelFactory* getInstance(gcmp::IDocument* pDoc);
        void SetStraightLineName(const std::wstring& name);
        const std::wstring& GetStraightLineName();

        gcmp::OwnerPtr<CommonLineStyleButtonModel> make(const LineStyleButtonModelType& type);
        const gcmp::ILineTypeNew* getLineTypeByName(const std::wstring& name);

        void setGraphicsStyleIds(const gcmp::ElementIdArray& ids, const std::vector<const gcmp::ILineTypeNew*>& datas);

        /// \brief 设置CAD的线宽数据，用来构造下拉菜单中线宽显示和信息
        /// \param std::vector<std::pair<int, double>> 数据信息
        /// - pair中的第一个int值代表线宽的像素宽度
        /// - pair中的第二个double值用来在线宽旁边宽度（mm）
        /// - 如{1, 0.7} 界面会展示 ---------------- 0.7mm
        /// \return 
        void setCadLineWidthData(const std::vector<std::pair<int, double>>& data);
        void setLineWidthData(const std::vector<int>& data);
    private:
        void setDocument(gcmp::IDocument* pDoc);

        LineStyleButtonModelFactory();
        ~LineStyleButtonModelFactory();

    private:
        gcmp::WeakPtr<gcmp::IDocument> m_pDoc;
        gcmp::ElementIdArray m_graphicsStyleId;
        std::vector<gcmp::WeakPtr<const gcmp::ILineTypeNew>> m_lineTypes;
        std::vector<int> m_lineWidthDatas;
        std::vector<std::pair<int, double>> m_cadlineWidthDatas;
        gcmp::OwnerPtr<LineStyleButtonModel> m_prototypeLineStyleModel;
        gcmp::OwnerPtr<LinePatternButtonModel> m_prototypeLinePatternModel;
        gcmp::OwnerPtr<LineWidthButtonModel> m_prototypeLineWidthModel;
        gcmp::OwnerPtr<CadLineWidthButtonModel> m_cadprototypeLineWidthModel;
        std::wstring  m_straightLineName = L"实线 (StraightLine)";
    };
}
